#ifndef __M_CONNECTION_H__
#define __M_CONNECTION_H__
#include "muduo/proto/dispatcher.h"
#include "muduo/proto/codec.h"
#include "muduo/base/Logging.h"
#include "muduo/base/Mutex.h"
#include "muduo/net/EventLoop.h"
#include "muduo/net/TcpClient.h"
#include "muduo/net/EventLoopThread.h"
#include "muduo/base/CountDownLatch.h"

#include "mq_channel.hpp"
#include "mq_worker.hpp"

namespace pprmq
{
    class Connection
    {
    public:
        using ptr = std::shared_ptr<Connection>;
        Connection(const std::string &sip, int sport,const AsyncWorker::ptr& worker)
            : _latch(1), _client(worker->loopthread.startLoop(), muduo::net::InetAddress(sip, sport), "Client"),
            _dispatcher(std::bind(&Connection::onUnknownMessage, this,
                                    std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)),
            _codec(std::make_shared<ProtobufCodec>(std::bind(&ProtobufDispatcher::onProtobufMessage, &_dispatcher,
                            std::placeholders::_1, std::placeholders::_2, std::placeholders::_3))),
            _worker(worker),_channel_manager(std::make_shared<ChannelManager>())
        {
            //注册业务请求处理函数
            _dispatcher.registerMessageCallback<basicCommonResponse>(std::bind(&Connection::basicResponse,this,
                std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
            _dispatcher.registerMessageCallback<basicConsumeResponse>(std::bind(&Connection::consumeResponse,this,
                std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));

            _client.setMessageCallback(std::bind(&ProtobufCodec::onMessage, _codec.get(),
                std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));

            _client.setConnectionCallback(std::bind(&Connection::onConnection, this,std::placeholders::_1));
            
            // 发起TCP连接
            _client.connect();
            // 阻塞等待
            _latch.wait();
        }

        // 打开一个新信道
        Channel::ptr openChannel()
        {
            Channel::ptr channel = _channel_manager->create(_conn,_codec);
            bool ret = channel->openChannel();
            if(ret == false)
            {
                DLOG("打开信道失败");
                return Channel::ptr();
            }
            return channel;
        }
        // 关闭指定信道
        void closeChannel(const Channel::ptr &channel)
        {
            channel->closeChannel(); // 向服务器发送关闭请求
            _channel_manager->remove(channel->cid()); // 从管理器中移除该信道
        }

    private:

        // 处理basicCommonResponse类型消息的回调
        void basicResponse(const muduo::net::TcpConnectionPtr& conn, const basicCommonResponsePtr& message, muduo::Timestamp)
        {
            // 首先根据消息中的信道ID查找对应的信道
            Channel::ptr channel = _channel_manager->get(message->cid());
            if(channel.get() == nullptr)
            {
                DLOG("未找到信道信息");
                return ;
            }
            return channel->putBasicResponse(message);
        }
        // 处理basicConsumeResponse类型消息的回调
        void consumeResponse(const muduo::net::TcpConnectionPtr& conn, const basicConsumeResponsePtr& message, muduo::Timestamp)
        {
            // 首先根据消息中的信道ID查找对应的信道
            Channel::ptr channel = _channel_manager->get(message->cid());
            if(channel.get() == nullptr)
            {
                DLOG("未找到信道信息");
                return ;
            }
            _worker->pool.push([channel,message](){
                channel->consume(message);
            });
        }

        void onUnknownMessage(const muduo::net::TcpConnectionPtr &conn, const MessagePtr &message, muduo::Timestamp)
        {
            LOG_INFO << "onUnknownMessage: " << message->GetTypeName();
            conn->shutdown();
        }

        void onConnection(const muduo::net::TcpConnectionPtr& conn)
        {
            if(conn->connected())
            {
                _conn = conn;
                _latch.countDown();//唤醒主线程中的阻塞
            }
            else
            {
                _conn.reset();
            }
        }

    private:
        muduo::CountDownLatch _latch;            // 保证同步关系
        muduo::net::TcpConnectionPtr _conn;      // TCP 连接智能指针，保存与服务器的连接对象
        muduo::net::TcpClient _client;           // TCP 客户端对象，用于与服务器建立连接和收发数据
        ProtobufDispatcher _dispatcher;          // 请求分发器
        ProtobufCodecPtr _codec;                    // 协议处理器
        
        AsyncWorker::ptr _worker;                     // 工作线程
        ChannelManager::ptr _channel_manager;    // 信道管理器智能指针
    };
}

#endif